package com.ethink.warehouse.facade.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ethink.framework.common.constant.CommonRespCode;
import com.ethink.framework.common.exception.BusinessException;
import com.ethink.warehouse.api.MateInventoryAdjustLogFacade;
import com.ethink.warehouse.api.enums.LogisticsTraceDetailOrderTypeEnum;
import com.ethink.warehouse.api.enums.MateInventoryAdjustLogOrderStatusEnum;
import com.ethink.warehouse.api.enums.SubjectEnum;
import com.ethink.warehouse.api.info.MateInventoryAdjustLogInfo;
import com.ethink.warehouse.api.info.MateInventoryAdjustLogModeInfo;
import com.ethink.warehouse.api.request.*;
import com.ethink.warehouse.api.response.MateInventoryAdjustLogAddResponse;
import com.ethink.warehouse.api.response.MateInventoryAdjustLogDeleteResponse;
import com.ethink.warehouse.api.response.MateInventoryAdjustLogGetDetailResponse;
import com.ethink.warehouse.api.response.MateInventoryAdjustLogUpdateResponse;
import com.ethink.warehouse.common.entity.MateInventory;
import com.ethink.warehouse.common.entity.MateInventoryAdjustLog;
import com.ethink.warehouse.common.entity.MateInventoryAdjustLogDetail;
import com.ethink.warehouse.common.mapper.MateInventoryAdjustLogDetailMapper;
import com.ethink.warehouse.common.mapper.MateInventoryAdjustLogMapper;
import com.ethink.warehouse.manager.MateInventoryManager;
import com.ethink.warehouse.service.MateInventoryAdjustLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 库存矫正记录 Facade接口实现
 *
 * @author default
 * @date 2022-11-17
 */
@RestController
@Slf4j
@RequestMapping("warehouse-service/facade/v1/mateInventoryAdjustLog")
public class MateInventoryAdjustLogFacadeImpl implements MateInventoryAdjustLogFacade {

    @Autowired
    private MateInventoryAdjustLogService mateInventoryAdjustLogService;
    @Autowired
    private MateInventoryAdjustLogMapper mateInventoryAdjustLogMapper;
    @Autowired
    private MateInventoryAdjustLogDetailMapper mateInventoryAdjustLogDetailMapper;
    @Autowired
    private MateInventoryManager mateInventoryManager;

    @Override
    public Page<MateInventoryAdjustLogInfo> queryMateInventoryAdjustLog(MateInventoryAdjustLogQueryRequest request) {
        return mateInventoryAdjustLogService.queryMateInventoryAdjustLog(request);
    }

    @Override
    public MateInventoryAdjustLogGetDetailResponse getMateInventoryAdjustLogById(Long mateInventoryAdjustLogId) {
        return mateInventoryAdjustLogService.getMateInventoryAdjustLogById(mateInventoryAdjustLogId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MateInventoryAdjustLogAddResponse addMateInventoryAdjustLog(MateInventoryAdjustLogAddRequest request) {
        MateInventoryAdjustLogAddResponse response = mateInventoryAdjustLogService.addMateInventoryAdjustLog(request);
        if (MateInventoryAdjustLogOrderStatusEnum.S2.eq(request.getOrderStatus())) {
            lock(response.getId());
        }
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MateInventoryAdjustLogUpdateResponse updateMateInventoryAdjustLog(MateInventoryAdjustLogUpdateRequest request) {
        MateInventoryAdjustLogUpdateResponse response = mateInventoryAdjustLogService.updateMateInventoryAdjustLog(request);
        if (MateInventoryAdjustLogOrderStatusEnum.S2.eq(request.getOrderStatus())) {
            lock(response.getId());
        }
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MateInventoryAdjustLogDeleteResponse deleteMateInventoryAdjustLog(Long id) {
        MateInventoryAdjustLog changeLog = mateInventoryAdjustLogMapper.selectById(id);
        if (MateInventoryAdjustLogOrderStatusEnum.S3.eq(changeLog.getOrderStatus())) {
            throw new BusinessException(CommonRespCode.SYSTEM_ERR, "订单已完成，无法撤销");
        }
        if (MateInventoryAdjustLogOrderStatusEnum.S2.eq(changeLog.getOrderStatus())) {
            // 需要释放库存
            List<MateInventoryAdjustLogDetail> changeLogDetails = mateInventoryAdjustLogDetailMapper.selectList(
                    new LambdaQueryWrapper<MateInventoryAdjustLogDetail>()
                            .eq(MateInventoryAdjustLogDetail::getOrderNo, changeLog.getOrderNo())
            );
            releaseLock(changeLog, changeLogDetails);
        }
        MateInventoryAdjustLogDeleteResponse response = mateInventoryAdjustLogService.deleteMateInventoryAdjustLog(id);
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approvedMateInventoryAdjustLog(Long id) {
        MateInventoryAdjustLog changeLog = mateInventoryAdjustLogMapper.selectById(id);
        if (!MateInventoryAdjustLogOrderStatusEnum.S2.eq(changeLog.getOrderStatus())) {
            throw new BusinessException(CommonRespCode.SYSTEM_ERR, "当前订单状态无法审批通过");
        }
        mateInventoryAdjustLogService.setOrderStatus(id, MateInventoryAdjustLogOrderStatusEnum.S3.getIntValue());
        List<MateInventoryAdjustLogDetail> changeLogDetails = mateInventoryAdjustLogDetailMapper.selectList(
                new LambdaQueryWrapper<MateInventoryAdjustLogDetail>()
                        .eq(MateInventoryAdjustLogDetail::getOrderNo, changeLog.getOrderNo())
        );
        releaseLock(changeLog, changeLogDetails);
        // 出库,入库
        Map<Long, MateInventory> map = mateInventoryManager.adjustMateInventory(changeLog, changeLogDetails);
        map.forEach((detailId, afterMateInventory) -> {
            mateInventoryAdjustLogDetailMapper.update(null,
                    new LambdaUpdateWrapper<MateInventoryAdjustLogDetail>()
                            .eq(MateInventoryAdjustLogDetail::getId, detailId)
                            .set(MateInventoryAdjustLogDetail::getAfterMateInventoryId, afterMateInventory.getId())
                            .set(MateInventoryAdjustLogDetail::getAdjustPurchaseCode, afterMateInventory.getPurchaseCode())
            );
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refuseMateInventoryAdjustLog(Long id) {
        MateInventoryAdjustLog changeLog = mateInventoryAdjustLogMapper.selectById(id);
        if (!MateInventoryAdjustLogOrderStatusEnum.S2.eq(changeLog.getOrderStatus())) {
            throw new BusinessException(CommonRespCode.SYSTEM_ERR, "当前订单状态无法审批拒绝");
        }
        mateInventoryAdjustLogService.setOrderStatus(id, MateInventoryAdjustLogOrderStatusEnum.S1.getIntValue());
        List<MateInventoryAdjustLogDetail> changeLogDetails = mateInventoryAdjustLogDetailMapper.selectList(
                new LambdaQueryWrapper<MateInventoryAdjustLogDetail>()
                        .eq(MateInventoryAdjustLogDetail::getOrderNo, changeLog.getOrderNo())
        );
        releaseLock(changeLog, changeLogDetails);
    }

    private void lock(Long id) {
        // 锁定库存
        MateInventoryAdjustLog changeLog = mateInventoryAdjustLogMapper.selectById(id);
        List<MateInventoryAdjustLogDetail> changeLogDetails = mateInventoryAdjustLogDetailMapper.selectList(
                new LambdaQueryWrapper<MateInventoryAdjustLogDetail>()
                        .eq(MateInventoryAdjustLogDetail::getOrderNo, changeLog.getOrderNo())
        );
        List<MateInventoryLockLogAddRequest> requests = new ArrayList<>();
        for (MateInventoryAdjustLogDetail changeLogDetail : changeLogDetails) {
            MateInventoryLockLogAddRequest request = new MateInventoryLockLogAddRequest();
            request.setOrderType(LogisticsTraceDetailOrderTypeEnum.T2.getIntValue());
            request.setSourceOrderNo(changeLog.getOrderNo());
            request.setSourceDetailOrderNo(changeLog.getOrderNo() + changeLogDetail.getId());
            request.setSourceOrderType(SubjectEnum.T82.getCode());
            request.setSubject(SubjectEnum.T82.getCode());
            request.setMateInventoryId(changeLogDetail.getBeforeMateInventoryId());
            request.setLockQty(changeLogDetail.getAdjustQty());
            requests.add(request);
        }
        mateInventoryManager.lockMateInventory(requests);
    }

    private void releaseLock(MateInventoryAdjustLog changeLog, List<MateInventoryAdjustLogDetail> changeLogDetails) {
        List<MateInventoryLockLogAddRequest> requests = new ArrayList<>();
        for (MateInventoryAdjustLogDetail changeLogDetail : changeLogDetails) {
            MateInventoryLockLogAddRequest request = new MateInventoryLockLogAddRequest();
            request.setOrderType(LogisticsTraceDetailOrderTypeEnum.T2.getIntValue());
            request.setSourceOrderNo(changeLog.getOrderNo());
            request.setSourceDetailOrderNo(changeLog.getOrderNo() + changeLogDetail.getId());
            request.setSourceOrderType(SubjectEnum.T82.getCode());
            request.setSubject(SubjectEnum.T82.getCode());
            request.setMateInventoryId(changeLogDetail.getBeforeMateInventoryId());
            request.setLockQty(changeLogDetail.getAdjustQty());
            requests.add(request);
        }
        mateInventoryManager.releaseLockMateInventory(requests);
    }

    @Override
    public Page<MateInventoryAdjustLogModeInfo> queryMateInventoryAdjustLogMode(MateInventoryAdjustLogQueryModeRequest request) {
        return mateInventoryAdjustLogService.queryMateInventoryAdjustLogMode(request);
    }
}